#include <stdio.h>
#include <video_encoder.h>

static const char *enc_option_string = "preset=fast,b=2000000,force_idr=interval:25,pts_passthrough=1";
static const char *enc_params_key = "enc_params";
static const char *enc_params_value = "low_delay=1:gop_size=1";

video_encoder::video_encoder(/* args */const char* codec_name,AVCodecParameters* codecpar,AVRational timebase)
{
    m_enc = avcodec_find_encoder_by_name(codec_name);
    if (!m_enc) {
        av_log(NULL, AV_LOG_FATAL, "Necessary encoder not found\n");
        av_log(NULL, AV_LOG_INFO, "Supported encoder: h264enc_vpe, hevcenc_vpe, vp9enc_vpe\n");        
    }
    m_enc_ctx = avcodec_alloc_context3(m_enc);
    if (!m_enc_ctx) {
        av_log(NULL, AV_LOG_FATAL,
                "Failed to allocate the encoder context\n");        
    }    
    m_timebase = timebase;
    m_codecpar = codecpar;
}
video_encoder::~video_encoder()
{

}
int  video_encoder::decode(AVPacket* pkt,AVFrame* frame,int eof,int& got,int* finished) 
{
    return 0;
}
int  video_encoder::encode(const AVFrame*  frame, AVPacket* pkt,int& got,int* finished) 
{
    int ret = 0;  
    got = 0;   
    if(!m_open) {
        AVDictionary *opts = NULL;
        m_enc_ctx->height = frame->height;
        m_enc_ctx->width = frame->width;
        m_enc_ctx->sample_aspect_ratio = frame->sample_aspect_ratio;
        m_enc_ctx->pix_fmt = AV_PIX_FMT_NV12;
        m_open = true;
        m_enc_ctx->time_base = m_timebase;
        m_enc_ctx->framerate = {1,25};

        //avcodec_parameters_to_context(m_enc_ctx, m_codecpar);
        av_dict_parse_string(&opts, enc_option_string, "=", ",", 0);
        av_dict_set(&opts, enc_params_key, enc_params_value, 0);
        ret = avcodec_open2(m_enc_ctx, m_enc, &opts);
        av_dict_free(&opts);
        if (ret < 0) {
            av_log(NULL, AV_LOG_ERROR,
               "Cannot open video encoder for stream, ret %d\n", ret);
            return ret;
        }
        m_open = true;
    }
    /* Third parameter can be used to pass settings to encoder */   
    ret = avcodec_send_frame(m_enc_ctx, frame);
    if (ret < 0) {
        fprintf(stderr, "Error sending a frame for encoding\n");
        return ret;
    }

    while (ret >= 0) {
        ret = avcodec_receive_packet(m_enc_ctx, pkt);
        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
            return 0;
        else if (ret < 0) {
            fprintf(stderr, "Error during encoding\n");
            return ret;
        } 
        m_frame_out_cnt++; 
        got = 1;
        return ret;      
    }

    return 0;
}
AVMediaType video_encoder::get_codec_type() const{
    return AVMEDIA_TYPE_VIDEO;
}